using Microsoft.Extensions.Hosting;
using admin.core.Entities.App;
using admin.core.Repositories;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using Dapper;

namespace admin.application.Services;

public class AppImageService : IAppImageService
{
    private readonly IHostEnvironment _env;
    private readonly IAppImageRepository _imageRepository;
    private readonly IDbConnection _dbConnection;

    public AppImageService(IHostEnvironment env, IAppImageRepository imageRepository, IDbConnection dbConnection)
    {
        _env = env;
        _imageRepository = imageRepository;
        _dbConnection = dbConnection;
    }

    public async Task<bool> IsValidImageAsync(string fileName, long fileSize, string contentType)
    {
        // 检查文件扩展名
        var extension = Path.GetExtension(fileName).ToLower();
        var validExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp" };
        
        if (!validExtensions.Contains(extension))
            return false;

        // 检查文件大小（默认10MB）
        if (fileSize > 10 * 1024 * 1024)
            return false;

        // 检查Content-Type
        var validContentTypes = new[] { 
            "image/jpeg", "image/jpg", "image/png", "image/gif", "image/bmp", "image/webp" 
        };
        
        if (!validContentTypes.Contains(contentType.ToLower()))
            return false;

        // 检查文件名是否已存在
        if (await _imageRepository.ExistsByFileNameAsync(fileName))
            return false;

        return true;
    }

    public string GenerateUniqueFileName(string originalFileName)
    {
        var extension = Path.GetExtension(originalFileName);
        var fileName = $"{Guid.NewGuid()}{extension}";
        return fileName;
    }

    public async Task<AppImage> CreateImageEntityAsync(
        string fileName, 
        string originalFileName, 
        string filePath, 
        long fileSize, 
        string contentType, 
        Guid userId, 
        string? description = null, 
        string? tags = null)
    {
        var image = new AppImage
        {
            Id = Guid.NewGuid(),
            FileName = fileName,
            OriginalFileName = originalFileName,
            FilePath = filePath,
            FileExtension = Path.GetExtension(originalFileName),
            FileSize = fileSize,
            ContentType = contentType,
            UserId = userId,
            Description = description,
            Tags = tags,
            IsActived = true,
            IsDeleted = false,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow,
            CreatedBy = userId,
            UpdatedBy = userId
        };

        return image;
    }

    public async Task<string> SaveImageAsync(Stream fileStream, string extension)
    {
        var uploads = Path.Combine(_env.ContentRootPath, "wwwroot", "images");
        if (!Directory.Exists(uploads))
            Directory.CreateDirectory(uploads);

        var fileName = Guid.NewGuid() + extension;
        var filePath = Path.Combine(uploads, fileName);

        using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await fileStream.CopyToAsync(stream);
        }

        return fileName;
    }

    public async Task<long> SaveImageInfoAsync(string fileName, string originalFileName, string filePath, string fileExtension, long fileSize, string contentType, string url, DateTime uploadTime, string? tags = null, string? description = null, Guid? userId = null)
    {
        var image = new admin.core.Entities.App.AppImage
        {
            Id = Guid.NewGuid(),
            FileName = fileName,
            OriginalFileName = originalFileName,
            FilePath = filePath,
            FileExtension = fileExtension,
            FileSize = fileSize,
            ContentType = contentType,
            Url = url,
            UploadTime = uploadTime,
            Tags = tags,
            Description = description,
            UserId = userId ?? Guid.Empty,
            IsActived = true,
            IsDeleted = false,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow,
            CreatedBy = userId ?? Guid.Empty,
            UpdatedBy = userId ?? Guid.Empty
        };
        return await _imageRepository.AddImageAsync(image);
    }

    public async Task<long> SaveImageInfoAsync(AppImage image)
    {
        return await _imageRepository.AddImageAsync(image);
    }

    public async Task<AppImage?> GetImageByFileNameAsync(string fileName)
    {
        return await _imageRepository.GetByFileNameAsync(fileName);
    }

    public async Task<IEnumerable<AppImage>> GetImagesByUserIdAsync(Guid userId)
    {
        return await _imageRepository.GetByUserIdAsync(userId);
    }

    public async Task<bool> DeleteImageAsync(Guid imageId)
    {
        try
        {
            // 调用仓储层删除图片记录
            return await _imageRepository.DeleteAsync(imageId);
        }
        catch
        {
            return false;
        }
    }

    public async Task<Dictionary<Guid, AppImage?>> GetAvatarsByUserIdsAsync(IEnumerable<Guid> userIds)
    {
        var dict = new Dictionary<Guid, AppImage?>();
        if (userIds == null) return dict;
        var idList = userIds.ToList();
        if (idList.Count == 0) return dict;

        // 用dbConnection批量查找所有相关图片
        var sql = @"SELECT * FROM ""AppImage"" WHERE ""UserId"" = ANY(@UserIds) AND ""IsDeleted"" = false;";
        var allImages = (await _dbConnection.QueryAsync<AppImage>(sql, new { UserIds = idList.ToArray() })).ToList();

        foreach (var uid in idList)
        {
            // 只取tags包含avatar的图片
            var avatar = allImages.FirstOrDefault(img => img.UserId == uid && !string.IsNullOrEmpty(img.Tags) && img.Tags.ToLower().Contains("avatar"));
            dict[uid] = avatar;
        }
        return dict;
    }

    public async Task<long> UpdateImageInfoAsync(AppImage image)
    {
        var sql = @"UPDATE ""AppImage"" SET ""IsDeleted"" = @IsDeleted, ""UpdatedAt"" = @UpdatedAt, ""UpdatedBy"" = @UpdatedBy WHERE ""Id"" = @Id;";
        return await _dbConnection.ExecuteAsync(sql, new { image.IsDeleted, image.UpdatedAt, image.UpdatedBy, image.Id });
    }
} 